home *** CD-ROM | disk | FTP | other *** search
-
-
- This is the sourcecode for a simple 8-way scrolling demo. It includes
- everything except the low-level pixel copying functions, which were
- written in assembly and gathered in the modexc.lib file. I expect that
- these are pretty standard functions, although your library no doubt
- uses different names and perhaps slightly different arguments.
-
- It also depends on having a .wld file in a format of my own devising,
- but you would have your own format for tiles and world maps, and
- functions for reading them in. That has nothing to do with the
- scrolling method anyway.
-
- This code is released to the public domain by the author. Learn from
- it, use it, rewrite it... whatever you will.
-
- -]Frank[-
-
- /* ------------------- file SCROLL.H ----------------------------------- */
-
- #define PG_WID 88
- #define WLD_WID 32
- #define WLD_HGT 17
-
- #define LOW_LIMIT 14848
-
- #define BALL_WID 16
- #define BALL_HGT 10
-
- typedef struct b { int x, y, oldx, oldy, xdir, ydir; } BALL;
-
- enum { SCROLL_N, SCROLL_NE, SCROLL_E, SCROLL_SE,
- SCROLL_S, SCROLL_SW, SCROLL_W, SCROLL_NW };
-
- extern char ballmap[];
- extern BALL *ball;
- extern char pal[3*256];
- extern char *tiles;
- extern char (*world)[WLD_WID];
- extern int world_rows, world_cols;
- extern int win_moved_x, win_moved_y;
-
- extern int deferred_copy;
-
- #define COPY_TOP 0x11
- #define COPY_BOT 0x21
- #define COPY_LFT 0x31
- #define COPY_RGT 0x41
- #define NOT_YET 0x01
-
- extern unsigned visible_off, active_off, back_off;
-
- extern int window_x, window_y;
- extern int world_x, world_y;
-
- /* functions */
-
- int read_world( char *fname, char **tiles, char **world,
- int *w_rows, int *w_cols, char *pal );
-
- void scroll_north( void ), scroll_south( void );
- void scroll_east( void ), scroll_west( void );
-
- void put_tile_row( unsigned pg_off, int row, char *tiles);
- void put_tile_col( unsigned pg_off, int col, char *tiles);
-
-
-
- /* -------------------- file SCROLL.C ------------------------------- */
-
- #include <headers.h>
- #include <modexc.h>
- #include "scroll.h"
-
- char ballmap[] = {
- 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 24, 24, 29, 29, 24, 24, 24, 24, 0, 0, 0, 0,
- 0, 0, 0, 24, 24, 29, 29, 24, 24, 24, 24, 24, 24, 0, 0, 0,
- 0, 0, 0, 24, 24, 29, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0,
- 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0,
- 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 23, 24, 24, 0, 0, 0,
- 0, 0, 0, 0, 24, 24, 24, 24, 24, 23, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 24, 24, 24, 24, 23, 23, 24, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0 };
-
-
- char pal[3*256];
- char *tiles;
- BALL *ball;
- int num_balls;
-
- char (*world)[WLD_WID];
- int world_rows, world_cols;
- int win_moved_x, win_moved_y;
- int deferred_copy = FALSE;
-
- unsigned visible_off = 360,
- active_off = 22208,
- back_off = 44052;
-
- int window_x = 16, window_y = 16;
- int world_x = 0, world_y = 0;
-
-
- /*+----------------------------------------------------------------------+
- | main() |
- +----------------------------------------------------------------------+*/
-
- void main( int argc, char *argv[] )
- {
- int i, dir=SCROLL_NE;
- unsigned utemp, frames=0;
- int old_win_x=0, old_win_y=0;
-
- if( argc != 2 ) num_balls = 8;
- else num_balls = atoi( argv[1] );
-
- if( num_balls > 0 )
- if( (ball=calloc(sizeof(BALL),num_balls)) == NULL )
- { puts("Not enough memory"); exit(1); }
-
- srand( *((int far *)0x0040006cL) );
-
- for( i=0; i<num_balls; i++ )
- {
- ball[i].x = rand()%220 + 50;
- ball[i].y = rand()%150 + 25;
- ball[i].xdir = (rand() & 1) == 1 ? 2 : -2;
- ball[i].ydir = (rand() & 1) == 1 ? 2 : -2;
- }
-
- if( !read_world("city1.wld", &tiles,
- &world, &world_rows, &world_cols, pal) )
- { puts("Can't read city1.wld"); exit(1); }
-
- set_mode_x();
- set_page_width( 88 );
- set_pallette( pal );
- window_at( visible_off, window_x, window_y );
-
- for( i=0; i<14; i++ )
- put_tile_row( back_off, i, tiles );
-
- rect_vram_to_vram( back_off, active_off, 0, 0, 352, 224 );
- rect_vram_to_vram( back_off, visible_off, 0, 0, 352, 224 );
-
- /******** main loop *********/
-
- while( gamekey() != ESC )
- {
- utemp = visible_off;
- visible_off = active_off;
- active_off = utemp;
- frames++;
-
- wait_retrace();
- window_at( visible_off, window_x, window_y );
-
- if( deferred_copy )
- {
- switch( deferred_copy )
- {
- case COPY_TOP :
- rect_vram_to_vram( back_off, active_off, 0, 0, 352, 16 );
- break;
- case COPY_BOT :
- rect_vram_to_vram( back_off, active_off, 0, 224, 352, 16 );
- break;
- case COPY_LFT :
- rect_vram_to_vram( back_off, active_off, 0, 0, 16, 240 );
- break;
- case COPY_RGT :
- rect_vram_to_vram( back_off, active_off, 336, 0, 16, 240 );
- break;
- case NOT_YET :
- deferred_copy = FALSE;
- break;
- }
- deferred_copy &= 0x01;
- }
-
- /* erase sprites from old positions */
- for( i=0; i<num_balls; i++ )
- rect_vram_to_vram( back_off, active_off,
- ball[i].oldx + old_win_x - win_moved_x,
- ball[i].oldy + old_win_y - win_moved_y,
- BALL_WID, BALL_HGT );
-
- /* do scrolling */
- win_moved_x = win_moved_y = 0;
-
- switch( dir )
- {
- case SCROLL_N : scroll_north();
- if( frames == 440 )
- { frames = 0; dir = SCROLL_SE; }
- break;
-
- case SCROLL_NE : scroll_east();
- scroll_north();
- if( frames == 523 )
- { frames = 0; dir = SCROLL_NW; }
- break;
-
- case SCROLL_E : scroll_east();
- if( frames == 650 )
- { frames = 0; dir = SCROLL_SW; }
- break;
-
- case SCROLL_SE : scroll_east();
- scroll_south();
- if( frames == 451 )
- { frames = 0; dir = SCROLL_E; }
- break;
-
- case SCROLL_S : scroll_south();
- if( frames == 542 )
- { frames = 0; dir = SCROLL_W; }
- break;
-
- case SCROLL_SW : scroll_west();
- scroll_south();
- if( frames == 369 )
- { frames = 0; dir = SCROLL_S; }
- break;
-
- case SCROLL_W : scroll_west();
- if( frames == 255 )
- { frames = 0; dir = SCROLL_NE; }
- break;
-
- case SCROLL_NW : scroll_west();
- scroll_north();
- if( frames == 560 )
- { frames = 0; dir = SCROLL_N; }
- break;
- }
-
- /* check page positions */
- if( active_off > 44416 )
- {
- utemp = active_off;
- active_off = back_off;
- back_off = utemp;
- }
-
- /* save frame of reference */
- old_win_x = window_x;
- old_win_y = window_y;
-
- for( i=0; i<num_balls; i++ )
- {
- BALL *this = &ball[i];
-
- /* save ball positions */
- this->oldx = this->x;
- this->oldy = this->y;
-
- /* update ball positions */
- this->x += this->xdir;
- this->y += this->ydir;
-
- /* check collisions */
- if( this->x < 2 || this->x > 301 )
- this->xdir = -(this->xdir);
- if( this->y < 2 || this->y > 188 )
- this->ydir = -(this->ydir);
-
- /* draw balls in new positions */
- spr_to_vram( ballmap, active_off,
- this->x + window_x,
- this->y + window_y,
- BALL_WID, BALL_HGT );
- }
- } /**** end main loop ****/
-
- free( tiles );
- free( world );
- setvmode( 3 );
- }
-
- /* ---------------------- file DOSCROLL.C ----------------------------- */
-
- #include <headers.h>
- #include <modexc.h>
- #include "scroll.h"
-
- /*+----------------------------------------------------------------------+
- | scroll_north() scroll_south() scroll_east() scroll_west() |
- +----------------------------------------------------------------------+*/
-
- void scroll_east( void )
- {
- if( ++window_x == 33 )
- {
- /* move all pages right one tile */
- visible_off += 4;
- active_off += 4;
- back_off += 4;
-
- /* move right in world */
- if( ++world_x == WLD_WID ) world_x = 0;
-
- /* grab new row of tiles */
- put_tile_col( active_off, 21, tiles );
-
- /* copy to other pages */
- rect_vram_to_vram( active_off, back_off, 336, 0, 16, 240 );
- deferred_copy = COPY_RGT;
-
- /* reposition window */
- window_x = 17;
- }
- win_moved_x = 1;
- }
-
- /*-------------------------------*/
-
- void scroll_west( void )
- {
- if( --window_x < 0 )
- {
- /* move all pages left one tile */
- visible_off -= 4;
- active_off -= 4;
- back_off -= 4;
-
- /* move left in world */
- if( --world_x < 0 ) world_x += WLD_WID;
-
- /* grab new row of tiles */
- put_tile_col( active_off, 0, tiles );
-
- /* copy to other pages */
- rect_vram_to_vram( active_off, back_off, 0, 0, 16, 240 );
- deferred_copy = COPY_LFT;
-
- /* reposition window */
- window_x = 15;
- }
- win_moved_x = -1;
- }
-
- /*-------------------------------*/
-
- void scroll_north( void )
- {
- if( --window_y < 0 )
- {
- /* check if we have deferred write pending */
- if( deferred_copy )
- {
- ++window_y; /* cancel move */
- return; /* wait until next time */
- }
-
- /* move all pages up one tile */
- visible_off -= 16*PG_WID;
- active_off -= 16*PG_WID;
- back_off -= 16*PG_WID;
-
- /* move up in world */
- if( --world_y < 0 ) world_y += WLD_HGT;
-
- /* grab new row of tiles */
- put_tile_row( active_off, 0, tiles );
-
- /* copy to other pages */
- rect_vram_to_vram( active_off, back_off, 0, 0, 352, 16 );
- deferred_copy = COPY_TOP;
-
- /* reposition window */
- window_y = 15;
- }
- win_moved_y = -1;
- }
-
- /*-------------------------------*/
-
- void scroll_south( void )
- {
- if( ++window_y == 20 )
- {
- /* check if we have deferred write pending */
- if( deferred_copy )
- {
- --window_y; /* cancel move */
- return; /* wait until next time */
- }
-
- /* grab new row of tiles */
- put_tile_row( active_off, 14, tiles );
-
- /* copy to other pages */
- rect_vram_to_vram( active_off, back_off, 0, 224, 352, 16 );
- deferred_copy = COPY_BOT;
- }
-
- else if( window_y == 33 )
- {
- /* move all pages down one tile */
- visible_off += 16*PG_WID;
- active_off += 16*PG_WID;
- back_off += 16*PG_WID;
-
- /* move down in world */
- if( ++world_y == WLD_HGT ) world_y = 0;
-
- /* reposition window */
- window_y = 17;
- }
- win_moved_y = 1;
- }
-
- /* ---------------------- file DOTILES.C ------------------------------- */
-
- #include <headers.h>
- #include <modexc.h>
- #include "scroll.h"
-
- /*+----------------------------------------------------------------------+
- | read_world() put_tile_row() put_tile_col() |
- +----------------------------------------------------------------------+*/
-
- int read_world( char *fname, char **tiles, char **world,
- int *w_rows, int *w_cols, char *pal )
- {
- signed char code, pix;
- int numtiles, r, c;
- char *p;
- FILE *fp;
-
- if( (fp=fopen(fname,"rb")) == NULL )
- return FALSE;
-
- numtiles = fgetc( fp );
-
- if( (*tiles=malloc(numtiles*256)) == NULL )
- { fclose(fp); return FALSE; }
-
- /* unpack tiles */
- p = *tiles;
- while( (code=fgetc(fp)) != 0 )
- {
- if( code > 0 )
- {
- pix = fgetc(fp);
- while( code-- ) *p++ = pix;
- }
- else
- while( code++ ) *p++ = fgetc(fp);
- }
-
- /* now do world */
- fread( w_rows, 2, 1, fp ); /* stored as ints */
- fread( w_cols, 2, 1, fp );
-
- if( *w_rows!=WLD_HGT || *w_cols!=WLD_WID )
- { puts("Wrong world size"); fclose(fp); return FALSE; }
-
- if( (*world=malloc((*w_rows)*(*w_cols))) == NULL )
- { fclose(fp); return FALSE; }
-
- fread( *world, *w_rows, *w_cols, fp );
-
- /* finally, the pallette */
- fread( pal, 3, 256, fp );
-
- fclose(fp); return TRUE;
- }
-
- /*-------------------------------*/
-
- void put_tile_row( unsigned pg_off, int row, char *tiles )
- {
- int c, wld_x, wld_y, tilenum;
- unsigned start_off;
-
- if( (wld_y = world_y + row) >= WLD_HGT ) wld_y -= WLD_HGT;
- wld_x = world_x;
-
- /* alias offset so multipication done just once */
- start_off = pg_off + ( (unsigned)PG_WID << 4 ) * row;
-
- for( c=0; c<22; c++ )
- {
- tilenum = world[wld_y][wld_x];
- ltile_to_vram( tiles, tilenum, start_off, c<<4, 0 );
-
- if( ++wld_x == WLD_WID ) wld_x = 0;
- }
- }
- /*-------------------------------*/
-
- void put_tile_col( unsigned pg_off, int col, char *tiles )
- {
- int r, wld_x, wld_y, tilenum;
-
- if( (wld_x = world_x + col) >= WLD_WID ) wld_x -= WLD_WID;
- wld_y = world_y;
-
- for( r=0; r<15; r++ )
- {
- tilenum = world[wld_y][wld_x];
- ltile_to_vram( tiles, tilenum, pg_off, col<<4, r<<4 );
-
- if( ++wld_y == WLD_HGT ) wld_y = 0;
- }
- }
- /*-------------------------------*/
-
-